home *** CD-ROM | disk | FTP | other *** search
- /**
- ** File ......... tracker.cpp
- ** Published .... 2004-04-20
- **/
- /*
- Copyright (C) 2004 grymse@alhem.net
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- #include <ListenSocket.h>
- #include <signal.h>
- #include "MyHandler.h"
- #include "TrackerSock.h"
- #include "MyMinderSocket.h"
- #include "MyMinionSocket.h"
-
- #define DEB(x)
-
- bool quit = false;
-
-
- void top(MyHandler& h)
- {
- std::string msg = "Tip_" + Utility::l2string(static_cast<MinderHandler&>(h).GetHostId());
- static_cast<MinderHandler&>(h).SendMessage(Utility::base64(msg));
- unlink("top_map.dot");
- FILE *fil;
- if ((fil = fopen("top_map.dot","wt")) != NULL)
- {
- fprintf(fil,"digraph \"G\" {\n");
- fprintf(fil,"\tedge [arrowhead=open]\n");
- #ifdef _WIN32
- std::string os = "Win32";
- #else
- std::string os = "Linux";
- #endif
- fprintf(fil,"\t\"%ld\" [label=\"%ld\\n%s\\n%s\" style=filled fillcolor=\"#e0e0e0\"]\n",
- static_cast<MinderHandler&>(h).GetHostId(),
- static_cast<MinderHandler&>(h).GetHostId(),
- h.GetVersion().c_str(),
- os.c_str());
- static_cast<MinderHandler&>(h).Tops(fil);
- fclose(fil);
- }
- }
-
-
- void sigint(int s) /* save+quit */
- {
- fprintf(stderr,"shutting down\n");
- quit = true;
- }
-
-
- void sigpipe(int s)
- {
- }
-
-
- void reg_minder(MyHandler& h,const std::string& cmd)
- {
- MyMinderSocket *m = new MyMinderSocket(h,h.GetString("server/announce_url") );
- m -> Init();
-
- m -> Function(cmd); // Hello / Goodbye
- m -> SetDeleteByHandler(true);
- m -> Open(h.GetString("minder/host"),h.GetInt("minder/port"));
- h.Add(m);
- m -> SetLocalIpPort(h.GetLocalAddress(),h.GetLocalPort());
- if (!m -> Connecting()) // connected
- {
- m -> SendHello();
- }
-
- }
-
-
- void connect(MyHandler& h)
- {
- if (h.Count() < h.GetInt("minion/max") )
- {
- ipaddr_t a;
- port_t p;
- std::string key;
- long host_id;
- if (h.GetHost(a,p,key,host_id))
- {
- MinionSocket *tmp = new MyMinionSocket(h,key,a,p);
- tmp -> Init();
- ipaddr_t my_ip;
- port_t my_port;
- h.GetMyIpPort(my_ip, my_port);
- tmp -> SetMyIpPort(my_ip,my_port);
- tmp -> SetRemoteHostId(host_id);
- {
- std::string t;
- tmp -> l2ip(a,t);
- DEB( printf("Connect to: %s:%d\n",t.c_str(),p);)
- }
- if (tmp -> Open(a,p))
- {
- tmp -> SetDeleteByHandler(true);
- h.Add(tmp);
- //
- tmp -> SendHello("Hello");
- }
- else
- if (tmp -> Connecting())
- {
- tmp -> SetDeleteByHandler(true);
- // check OnConnect
- h.Add(tmp);
- }
- else
- {
- delete tmp;
- }
- }
- else
- {
- DEB( printf("h.GetHost() failed?\n");)
- }
- }
- }
-
-
- //////// overrides config file
- /*
- --port <arg>
- Port to listen on. (defaults to 80)
- OK
-
- --dfile <arg>
- file to store recent downloader info in
-
- --bind <arg>
- ip to bind to locally (defaults to '')
- OK
-
- --socket_timeout <arg>
- timeout for closing connections (defaults to 15)
-
- --save_dfile_interval <arg>
- seconds between saving dfile (defaults to 300)
-
- --timeout_downloaders_interval <arg>
- seconds between expiring downloaders (defaults to 2700)
- OK
-
- --reannounce_interval <arg>
- seconds downloaders should wait between reannouncements (defaults to
- 1800)
- OK
-
- --response_size <arg>
- number of peers to send in an info message (defaults to 50)
- OK
-
- --timeout_check_interval <arg>
- time to wait between checking if any connections have timed out
- (defaults to 5)
- OK
-
- --nat_check <arg>
- whether to check back and ban downloaders behind NAT (defaults to 1)
-
- --min_time_between_log_flushes <arg>
- minimum time it must have been since the last flush to do another one
- (defaults to 3.0)
-
- --allowed_dir <arg>
- only allow downloads for .torrents in this dir (defaults to '')
-
- --parse_allowed_interval <arg>
- minutes between reloading of allowed_dir (defaults to 15)
-
- --show_names <arg>
- whether to display names from allowed dir (defaults to 1)
-
- --favicon <arg>
- file containing x-icon data to return when browser requests
- favicon.ico (defaults to '')
-
- --only_local_override_ip <arg>
- ignore the ip GET parameter from machines which aren't on local
- network IPs (defaults to 1)
-
- --logfile <arg>
- file to write the tracker logs, use - for stdout (default) (defaults
- to '')
-
- --allow_get <arg>
- use with allowed_dir; adds a /file?hash={hash} url that allows users
- to download the torrent file (defaults to 0)
-
- --keep_dead <arg>
- keep dead torrents after they expire (so they still show up on your
- /scrape and web page) (defaults to 0)
-
- --max_give <arg>
- maximum number of peers to give with any one request (defaults to
- 200)
- */
-
-
- int main(int argc,char *argv[])
- {
- MyHandler h( "config.xml" );
- ListenSocket<TrackerSock> l(h);
- ListenSocket<MyMinionSocket> l3(h);
-
- signal(SIGINT, (__sighandler_t)sigint);
- signal(SIGHUP, (__sighandler_t)sigint);
- signal(SIGTERM,(__sighandler_t)sigint);
- signal(SIGPIPE, (__sighandler_t)sigpipe);
-
- // http tracker
- if (h.GetString("server/type") == "normal")
- {
- std::string bind = h.GetString("server/bind");
- port_t port = h.GetInt("server/port");
- int queue_size = h.GetInt("server/queue_size");
- {
- if (l.Bind(bind,port,queue_size))
- {
- return -1;
- }
- h.Add(&l);
- }
- }
- else
- if (h.GetString("server/type") == "ssl")
- {
- printf("Tracker type not implemented: 'ssl'\n");
- exit(-1);
- }
- else
- {
- printf("Tracker type not supported: '%s'\n",h.GetString("server/type").c_str());
- exit(-1);
- }
- // minion
- {
- std::string bind = h.GetString("minion/bind");
- port_t port = h.GetInt("minion/port");
- while (l3.Bind(port))
- {
- port++;
- }
- h.Add(&l3);
- h.SetLocalPort(port);
- }
- // main loop
- {
- time_t t = time(NULL); // send peer list (update)
- time_t tc = time(NULL); // connect
- time_t tm = time(NULL); // reg_minder
- time_t tt = time(NULL); // top
- time_t td = time(NULL); // dropped
- reg_minder(h,"Hello");
- h.Select(1,0);
- while (h.GetCount() && !quit)
- {
- h.Select(1,0);
- time_t t2 = time(NULL);
- if (t2 - tc > h.GetInt("minion/connect_interval") && h.GetInt("minion/connect_interval") )
- {
- tc = t2;
- connect(h);
- }
- if (t2 - t > h.GetInt("minion/update_interval"))
- {
- t = t2;
- h.SendList();
- }
- if (t2 - tm > 15 * 60)
- {
- tm = t2;
- reg_minder(h,"Hello");
- }
- if (t2 - tt > h.GetInt("minion/top_interval") && h.GetInt("minion/top_interval") ) // var femte minut
- {
- tt = t2;
- top(h);
- }
- if (t2 - td > h.GetInt("server/timeout_check_interval") )
- {
- td = t2;
- h.CheckDropped();
- }
- }
- }
- // shutdown
- {
- reg_minder(h,"Goodbye");
- h.Select(1,0);
- while (h.MinderSockets())
- {
- h.Select(1,0);
- }
- }
- }
-
-
-